Skip to main content

Axir Verifying Paymaster

The Axir Verifying Paymaster is an ERC-4337 compliant Paymaster contract that uses an external service to decide whether to pay for a UserOperation. It trusts an external signer to validate and sign transactions before they are submitted on-chain.

Overview

This paymaster relies on an off-chain service to perform validations and sign UserOperations. The user must first submit their UserOperation to this external service, which then signs it if it passes the off-chain verification process. This signature is then included in the paymasterAndData field of the UserOperation.

Key features:

  • Off-chain validation and signing
  • On-chain signature verification
  • Configurable validity period for UserOperations
  • Gas balance tracking and deduction

Contract Details

  • License: GPL-3.0
  • js Version: 0.8.23
  • Base Contract: BasePaymaster

Constructor

constructor(
IEntryPoint _entryPoint,
address _verifyingSigner
) payable BasePaymaster(_entryPoint)

Initializes the Axir Verifying Paymaster contract with the following parameters:

  • _entryPoint: The ERC-4337 EntryPoint contract
  • _verifyingSigner: The address of the trusted external signer

Key Functions

getHash

function getHash(
PackedUserOperation calldata userOp,
uint48 validUntil,
uint48 validAfter
) public view returns (bytes32)

Calculates the hash of the UserOperation that will be signed off-chain and validated on-chain. This hash includes all fields of the UserOperation except for paymasterAndData.

_validatePaymasterUserOp

function _validatePaymasterUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 requiredPreFund
) public view override returns (bytes memory context, uint256 validationData)

Verifies that the external signer has signed the UserOperation. It checks the signature included in the paymasterAndData field.

parsePaymasterAndData

function parsePaymasterAndData(
bytes calldata paymasterAndData
) public pure returns (uint48 validUntil, uint48 validAfter, bytes calldata signature)

Parses the paymasterAndData field to extract the validity period and signature.

_postOp

function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost,
uint256 actualUserOpFeePerGas
) internal virtual override

Executes the paymaster's payment conditions after the UserOperation has been processed. It deducts the gas cost from the paymaster's balance.

Events

GasBalanceDeducted

event GasBalanceDeducted(
address indexed _paymaster,
uint256 indexed _amount
)

Emitted when gas balance is deducted from the paymaster.

Paymaster Data Structure

The paymasterAndData field in the UserOperation should be structured as follows:

  • [:20]: address of this paymaster
  • [20:84]: abi.encode(validUntil, validAfter)
  • [84:]: signature

Security Considerations

  • The contract relies on the integrity of the external signer. Compromise of the signer's private key could lead to unauthorized UserOperations being approved.
  • The validity period (validUntil, validAfter) should be carefully set to prevent replay attacks.
  • The contract does not implement a deposit system, so the contract owner must ensure sufficient balance for gas payments.

Usage

  1. User creates a UserOperation
  2. User sends the UserOperation to the off-chain service
  3. Off-chain service validates the UserOperation and signs it
  4. User includes the signature and validity period in the paymasterAndData field
  5. User submits the UserOperation to the EntryPoint
  6. EntryPoint calls the paymaster to validate the UserOperation
  7. Paymaster verifies the signature and validity period
  8. If valid, the UserOperation is executed, and the paymaster pays for the gas
note

This paymaster design separates the concerns of account validation (done by the account itself) and payment authorization (done by the paymaster). The off-chain service can implement complex logic and integrations to decide whether to sponsor a transaction.